#ifndef VEC4_H_
#define VEC4_H_

#include "Vec3.h"

class File;

class Vec4
{
public:
    /* Default ctr*/
    Vec4() : 
    m_w(1), m_x(0), m_y(0), m_z(0) 
    {}  
    /* Copy Constructor */
    Vec4(const Vec4& v) : 
    m_w(v.GetW()), m_x(v.GetX()), m_y(v.GetY()), m_z(v.GetZ())
    {}
    /* Overloaded ctr */
    Vec4(const Vec3& v) :
    m_w(1), m_x(v.X()), m_y(v.Y()), m_z(v.Z()) 
    {}
    /* Overloaded ctr */
    Vec4(const float x, const float y, const float z, const float w = 1) :
    m_w(w), m_x(x), m_y(y), m_z(z) 
    {}

    /* Const Get Functions. */
    float GetW() const
    {
        return m_w;
    }
    float GetX() const
    {
        return m_x;
    }
    float GetY() const
    {
        return m_y;
    }
    float GetZ() const
    {
        return m_z;
    }
    /* Non Const Get Functions. */
    float& GetW()
    {
        return m_w;
    }
    float& GetX()
    {
        return m_x;
    }
    float& GetY()
    {
        return m_y;
    }
    float& GetZ()
    {
        return m_z;
    }
    /* Set Functions. */
    void SetW ( const float w)
    {
        m_w = w;
    }
    void SetX ( const float x)
    {
        m_x = x;
    }
    void SetY ( const float y)
    {
        m_y = y;
    }
    void SetZ ( const float z)
    {
        m_z = z;
    }
    void SetStats(const float x, const float y, const float z, const float w = 1)
    {
        m_w = w;
        m_x = x;
        m_y = y;
        m_z = z;
    }

    /* Returns the Vec3 corresponding to the homogeneous coordinate
     *  formed by the Vec 4
     */
    Vec3 GetVec3() const
    {
        return Vec3( m_x / m_w,
                        m_y / m_w,
                        m_z / m_w);
    }

    /* Index operators returning by value or reference. 
     * depending on constness 
     */
    float operator[](unsigned i) const
    {
        if (i == 0) return m_x;
        if (i == 1) return m_y;
        if (i == 2) return m_z;
        return m_w;
    }

    float& operator[](unsigned i) 
    {
        if (i == 0) return m_x;
        if (i == 1) return m_y;
        if (i == 2) return m_z;
        return m_w;
    }

    bool Load(File* f);
private :
    float m_w;
    float m_x;
    float m_y;
    float m_z;
};


#endif